#!/usr/bin/env python
# -*- coding: utf8 -*-
import mediawiki
import re
import settings
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import memcache

class autoConvert:
    def __init__(self, group, link, description = None):
        self.prefix = u'Template:CGroup'
        self.variants = ['zh-hans', 'zh-hant', 'zh-cn', 'zh-hk', 'zh-sg', 'zh-tw']
        self.fallback = {'zh-hans': ['zh-cn','zh-sg'],
                         'zh-cn': ['zh-sg'],
                         'zh-sg': ['zh-cn'],
                         'zh-hant': ['zh-tw','zh-hk'],
                         'zh-tw': ['zh-hk'],
                         'zh-hk': ['zh-tw']
                         }

        varsep_pattern = ';\s*(?='
        for variant in self.variants:
            varsep_pattern += '%s\s*:|' % variant # zh-hans:xxx;zh-hant:yyy
            varsep_pattern += '[^;]*?=>\s*%s\s*:|' % variant # xxx=>zh-hans:yyy; xxx=>zh-hant:zzz
        varsep_pattern += '\s*$)'
        self.varsep = re.compile(varsep_pattern)
        
        self.site = mediawiki.login(sysop = True)
        self.group = group
        self.convertrules = {'zh-hans': {},
                             'zh-hant': {},
                             'zh-cn':   {},
                             'zh-hk':   {},
                             'zh-sg':   {},
                             'zh-tw':   {}}
        if not description:
            description = link
        self.header = u'<noinclude>[[Category:公共轉換組模板|{{SUBPAGENAME}}]]</noinclude>' + \
                      u'本文采用[[%s|<span style="{{{linkStyle|}}}">%s</span>]]组全文转换' + \
                      u'<span class="editlink noprint plainlinksneverexpand">' + \
                      u' &#x5b;[[Template:CGroup/%s/temp|-{zh-cn:查看; zh-tw:檢視}-]]&#x5d; •' + \
                      u' &#x5b;[{{fullurl:Template:CGroup/%s/temp|action=edit}} 编辑]&#x5d; •' + \
                      u' &#x5b;[http://philip-bot.appspot.com/autoconvert?group=%s 强制-{zh-cn:刷新; zh-tw:更新;}-]&#x5d;</span>\n\n'
        self.header = self.header % (link, description, group, group, group)

    def _retrieveData(self):
        data = self.site.expandTemplates(u'{{:%s/%s/temp}}' % (self.prefix, self.group))
        return data

    def convert(self):
        data = self._retrieveData()
        allrules = re.findall('-\{\s*[D]\s*\|\s*([\s\S]+?)\s*\}-',data)
        for rule in allrules:
            bidtable = {}
            unidtable = {}
            all = ''
            choices = self.varsep.split(rule)
            for choice in choices:
                variant = choice.split(':', 1)
                if len(variant) != 2:
                    all = variant[0]
                    continue
                to = variant[1].strip()
                variant = variant[0].strip()
                unid = variant.split('=>', 1)
                # if to is empty, strtr() could return a wrong result
                if len(unid) == 1 and to and variant in self.variants:
                    bidtable[variant] = to
                elif len(unid) == 2:
                    frm = unid[0].strip()
                    variant = unid[1].strip()
                    if not unidtable.get(variant):
                        unidtable[variant] = {}
                    if to and variant in self.variants:
                        unidtable[variant][frm] = to

            if all:
                for variant in self.variants:
                    self.convertrules[variant][all] = all

            bidfroms = bidtable.values()
            for (variant, to) in bidtable.items():
                for frm in bidfroms:
                    self.convertrules[variant][frm] = to
                    fbs = self.fallback[variant]
                    for fbv in fbs:
                        if not self.convertrules[fbv].get(frm):
                            self.convertrules[fbv][frm] = to

            for variant in unidtable.keys():
                self.convertrules[variant].update(unidtable[variant])
        newdata = self._output()
        self._post(newdata)

    def _output(self):
        data = self.header + '-{H|\n'
        for variant in self.variants:
            froms = list(self.convertrules[variant].keys())
            froms.sort()
            for frm in froms:
                data += '  %s=>%s:%s;\n' % (frm, variant, self.convertrules[variant][frm])
        data += '}-'
        return data

    def _post(self, data):
        page = self.site(u'%s/%s' % (self.prefix, self.group))
        summary = u'机器人：更新优化组转换规则（beta）'
        rev = mediawiki.Revision(data, summary, bot = True)
        page.appendRevision(rev)

class AutoConvertPage(webapp.RequestHandler):
    
    groups = {u'IT': (u'Portal:电脑和信息技术', u'-{zh-cn:电脑和信息技术; zh-tw:電腦和資訊科技;}-')}
    
    def get(self):
        iscron = self.request.headers.get('x-appengine-cron')
        if iscron and iscron.lower() == 'true':
            for (group, params) in self.groups.items():
                if len(params) == 1:
                    ac = autoConvert(group, params[0], params[0])
                else:
                    ac = autoConvert(group, params[0], params[1])
                ac.convert()
            self.response.out.write(u'''
            <html>
              <body>
              Cron序列已成功完成。
              </body>
            <html>''')
        else:
            group = self.request.get('group')
            if self.groups.get(group):
                self.response.out.write(u'''
                <html>
                  <body>
                    <form action="autoconvert" method="post">
                      <input type="hidden" name="group" value="%s" />
                      <input id="save" name="save" type="submit" value="强制刷新" />
                    </form>
                  </body>
                </html>''' % group)
            else:
                self.response.out.write(u'''
                <html>
                  <body>
                  抱歉，您提交的参数有误。
                  </body>
                <html>''')

    def post(self):
        group = self.request.get('group')
        params = self.groups.get(group)
        if params:
            if memcache.get('autoconvert-throttle'):
                self.response.out.write(u'Please come back later.')
                return
            try:
                if len(params) == 1:
                    ac = autoConvert(group, params[0], params[0])
                else:
                    ac = autoConvert(group, params[0], params[1])
                ac.convert()
            except Exception, e:
                self.response.out.write(u'''
                <html>
                  <body>
                    <form action="autoconvert" method="post">
                      <input type="hidden" name="group" value="%s" />
                      发生错误（%s），请重试：<input id="save" name="save" type="submit" value="强制刷新" />
                    </form>
                  </body>
                </html>''' % (group, e))
                return 1
            memcache.set('autoconvert-throttle', True, settings.autoconvert_throttle)
            self.response.out.write(u'''
            <html>
              <body>
              强制刷新已成功完成。
              </body>
            <html>''')
        else:
            self.response.out.write(u'''
                <html>
                  <body>
                  抱歉，您提交的参数有误。
                  </body>
                <html>''')

application = webapp.WSGIApplication([('/autoconvert', AutoConvertPage)])

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()
